/*
 * Platzad
 * Copyright 2008 Shayne Riley
 *
 * This file is part of Platzad.
 *
 * Platzad is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Platzad is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Platzad.  If not, see <http://www.gnu.org/licenses/>.
 *
 * To contact the authors on questions or issues regarding the license,
 * you may send an email to <shayner at gmail dot com> or write to
 * Shayne Riley / P.O. Box 1092 / McCook, NE 69001.
 */

#ifndef AUDIO_H_
#define AUDIO_H_

#include <iostream>
#include <SDL/SDL_mixer.h>

namespace pzdAudio
{
//! Audio sub-system.
/**
 * Once used, spawns a thread used for all aural goodness. Everything is
 * self-contained, meaining the client has no methods that can be used on this
 * system.
 *
 * To use the audio system, use Audio, the safe interface for the
 * sub-system.
 */
class Audio
{
    public:
    	/// @brief Gives access to the only control instance.
    	static Audio& getInstance();

    	/**
    	 * @brief Loads new BackGround Music.
    	 *
    	 * Usable audio types are wav and Ogg Vorbis. So there. You must pause
    	 * the background music before loading a new song. If the file was
    	 * successfully loaded, it can be played when playBGM() is called. If
    	 * the file was not successfully loaded, playBGM() will result in
    	 * silence.
    	 *
    	 *
    	 * @param bgmFile	the file to play in the background.
    	 *
    	 * @return true if the file loaded and will play successfully. False
    	 * 	if the file was not found, or if the previous BGM was playing, or
    	 *  if the file is not a compatible audio type, or a million other
    	 * 	reasons.
    	 */
    	bool loadBGM(std::string bgmFile);

    	/**
    	 * @brief Plays whatever BackGround Music was loaded.
    	 *
    	 * Resumes playing the music from where it left off if previously
    	 * paused.
    	 */
    	void playBGM();

    	/// @brief Pauses the BackGround Music.
    	void pauseBGM();

    	/**
    	 * @brief Load the only audio clip to play.
    	 *
    	 * - Usable formats are wav and Ogg Vorbis.
    	 * - Although long audio files can be loaded, avoid doing it.
    	 * - Any previous audio file that was in memory will be erased when
    	 *   this is called. If an audio clip attempts to load but fails, no
    	 *   audio will play.
    	 *
    	 * @param filename	the file to load as the only audio clip.
    	 *
    	 * @return	true if the file loaded properly and will play successfully.
    	 *  False will be returned if the file was not found or could not be
    	 *  read, or if the file was not a compatible audio type.
    	 */
    	bool loadAudio(std::string filename);

    	/// @brief Play the audio clip.
    	void playAudio();

    private:
    	/// @brief Samples per second to play audio.
    	static const int AUDIO_RATE = 44100;
    	/// @brief Determines size of each sample and endianness.
    	static const Uint16 AUDIO_FORMAT = AUDIO_S16SYS;
    	/// @brief Number of channels to use.
    	static const int AUDIO_CHANNELS = 2;
    	/// @brief Maximum size of the audio buffers in bytes.
    	static const int AUDIO_BUFFER_SIZE = 4096;

    	/**
    	 * @brief Constructor for the display sub-system.
    	 *
    	 * There should only be one display-subsystem. Making the constructor
    	 * private ensures this happens.
    	 */
        Audio();

        /// @brief Destructor for a class that will never be derived from.
        ~Audio();

        /// @brief Does all the initialization for the class.
        void init();

        /// @brief Does all the cleaning up and such for the class.
        void finalize();

        /// @brief No copying needed, do not allow.
        /// Copy ctor declared, not defined.
        Audio(const Audio& rhs);
        /// @brief No assignment needed. Do not define this function.
        Audio& operator=(const Audio rhs);
        /// @brief No address-of needed. Do not define this function.
        Audio* operator&();
        /// @brief No const address-of needed. Do not define this function.
        const Audio* operator&() const;

        /// @brief The audio system is available when true.
        bool mAudioGood;

        /// @brief Play music if true.
        bool mPlayBGM;

        /// @brief The only audio sample to play.
        Mix_Chunk *audio;
        /// @brief The only music to play in the background.
        Mix_Music *music;

};

} // namespace
#endif /*AUDIO_H_*/
